package com.sikulifang.bank.simulation.util;

import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.kqueue.KQueueEventLoopGroup;
import io.netty.channel.kqueue.KQueueServerSocketChannel;
import io.netty.channel.kqueue.KQueueSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.Locale;
import java.util.Optional;

/**
 * 操作系统判定类，给netty启动时选择
 *
 * @author zhoul
 */
@Slf4j
public class OsHelper {

    private static final String MAC = "mac";

    private static final String WIN = "win";

    private static final String AIX = "aix";

    private static final String NIX = "nix";

    private static final String NUX = "nux";

    private static final OsEnum OS = parseOs();

    public static Class<? extends ServerSocketChannel> serverSocketChannelClazz() {
        return OS.serverSocketChannelClazz;
    }

    public static Class<? extends SocketChannel> socketChannelClazz() {
        return OS.socketChannelClazz;
    }

    public static EventLoopGroup buildEventLoopGroup(int num) {
        return OS.buildEventLoopGroup(num);
    }

    public static boolean isUnix() {
        return OS.equals(OsEnum.Unix);
    }

    public static boolean isWindows() {
        return OS.equals(OsEnum.Windows);
    }

    public static boolean isMac() {
        return OS.equals(OsEnum.MacOS);
    }

    private static OsEnum parseOs() {
        String osName = System.getProperty("os.name");
        osName = Optional.ofNullable(osName).orElse("").toLowerCase(Locale.ROOT);
        if ((osName.contains(WIN))) {
            return OsEnum.Windows;
        } else if (osName.contains(MAC)) {
            return OsEnum.MacOS;
        } else if (osName.contains(NIX) || osName.contains(NUX) || osName.indexOf(AIX) > 0) {
            return OsEnum.Unix;
        } else {
            return OsEnum.Other;
        }
    }

    private enum OsEnum {
        /**
         * 苹果操作系统
         */
        MacOS("mac", KQueueServerSocketChannel.class, KQueueSocketChannel.class) {
            @Override
            EventLoopGroup buildEventLoopGroup(int num) {
                return new KQueueEventLoopGroup(num);
            }
        },
        /**
         * unix内核操作系统
         */
        Unix("unix", EpollServerSocketChannel.class, EpollSocketChannel.class) {
            @Override
            EventLoopGroup buildEventLoopGroup(int num) {
                return new EpollEventLoopGroup(num);
            }
        },
        /**
         * window操作系统
         */
        Windows("windows", NioServerSocketChannel.class, NioSocketChannel.class) {
            @Override
            EventLoopGroup buildEventLoopGroup(int num) {
                return new NioEventLoopGroup(num);
            }
        },
        /**
         * 其他操作系统
         */
        Other("other", NioServerSocketChannel.class, NioSocketChannel.class) {
            @Override
            EventLoopGroup buildEventLoopGroup(int num) {
                return new NioEventLoopGroup(num);
            }
        };

        final String name;

        final Class<? extends ServerSocketChannel> serverSocketChannelClazz;

        final Class<? extends SocketChannel> socketChannelClazz;

        OsEnum(String name, Class<? extends ServerSocketChannel> serverSocketChannelClass, Class<?
                extends SocketChannel> socketChannelClass) {
            this.name = name;
            this.serverSocketChannelClazz = serverSocketChannelClass;
            this.socketChannelClazz = socketChannelClass;
        }

        abstract EventLoopGroup buildEventLoopGroup(int num);
    }
}

